package com.wei;

import java.util.ArrayList;
import java.util.List;

import com.wei.model.Coordinate;
import com.wei.model.Extent;
import com.wei.model.Size;
import com.wei.model.TileCoord;

import lombok.extern.log4j.Log4j;

@Log4j
public class BaiduTileGrid {

	private double[] resolutions;
	private Extent extent;
	private Coordinate origin;
	private Size tileSize;
	private List<Extent> tileRanges;
	private double totalTile;
	
	public List<Extent> getTileRanges() {
		return this.tileRanges;
	}
	
	public double getTotalTile() {
		return this.totalTile;
	}

    public BaiduTileGrid(double[] resolutions, Extent extent, Coordinate origin,Size tileSize)
    {
        this.resolutions = resolutions;
        this.extent = extent;
        this.origin = origin;
        this.tileSize = tileSize;
        this.tileRanges = calculateTileRanges();
    }
    
    private List<Extent> calculateTileRanges()
    {
        List<Extent> result = new ArrayList<Extent>();
        for (int i = 0, len = resolutions.length; i < len; i++)
        {
        	Coordinate leftBottomTileCoord = getTileCoordByXYAndZoom(i, this.extent.getLeftBottom(), false);
        	Coordinate rightTopTileCoord = getTileCoordByXYAndZoom(i, this.extent.getTopRight(), true);
            result.add(new Extent(leftBottomTileCoord, rightTopTileCoord));
            totalTile += (rightTopTileCoord.getX() - leftBottomTileCoord.getX() + 1 ) * (rightTopTileCoord.getY() - leftBottomTileCoord.getY() +1);
        }
        log.info("extent:"+extent.toString()+"视野范围预计总瓦片个数为:"+totalTile);
        return result;
    }
	
    private Coordinate getTileCoordByXYAndZoom(int zoom, Coordinate coord, boolean reverseIntersectionPolicy)
    {
        double adjustX = reverseIntersectionPolicy ? 0.5 : 0.0;
        double adjustY = reverseIntersectionPolicy ? 0.0 : 0.5;
        double resolution = this.resolutions[zoom];
        double xFromOrigin = Math.floor((coord.getX() - this.origin.getX()) / resolution + adjustX);
        double yFromOrigin = Math.floor((coord.getY() - this.origin.getY()) / resolution + adjustY);
        double tileCoordX = xFromOrigin / this.tileSize.getWidth();
        double tileCoordY = yFromOrigin / this.tileSize.getHeight();
        if (reverseIntersectionPolicy)
        {
            tileCoordX = Math.ceil(tileCoordX) - 1;
            tileCoordY = Math.ceil(tileCoordY) - 1;
        }
        else
        {
            tileCoordX = Math.floor(tileCoordX);
            tileCoordY = Math.floor(tileCoordY);
        }
        return new Coordinate(tileCoordX, tileCoordY);
    }
    
    public Extent getTileExtent(TileCoord tileCoord)
    {
    	Coordinate origin = this.origin;
        double resolution = this.resolutions[tileCoord.getZoom()];
        Size tileSize = this.tileSize;
        double minX = origin.getX() + tileCoord.getX() * tileSize.getWidth() * resolution;
        double minY = origin.getY()+ tileCoord.getY() * tileSize.getHeight() * resolution;
        double maxX = minX + tileSize.getWidth() * resolution;
        double maxY = minY + tileSize.getHeight() * resolution;
        return new Extent(minX, minY, maxX, maxY);
    }
}
